package cn.devzyh.oms.wsms.service.impl;

import cn.devzyh.oms.common.rabbitmq.queue.WsmsQueues;
import cn.devzyh.oms.common.security.util.SecurityUtils;
import cn.devzyh.oms.wsms.api.constant.StockConstants;
import cn.devzyh.oms.wsms.api.dto.StockDTO;
import cn.devzyh.oms.wsms.api.dto.StockLogDTO;
import cn.devzyh.oms.wsms.api.dto.StockUpdateDTO;
import cn.devzyh.oms.wsms.api.entity.Stock;
import cn.devzyh.oms.wsms.api.entity.StockLog;
import cn.devzyh.oms.wsms.api.vo.StockLogVO;
import cn.devzyh.oms.wsms.api.vo.StockQuantityVO;
import cn.devzyh.oms.wsms.mapper.StockLogMapper;
import cn.devzyh.oms.wsms.service.StockLogService;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class StockLogServiceImpl extends ServiceImpl<StockLogMapper, StockLog> implements StockLogService {

	private final StockLogMapper stockLogMapper;

	private final AmqpTemplate amqpTemplate;

	@Override
	public List<StockLogVO> list(IPage<StockLog> page, StockLogDTO sl) {
		return stockLogMapper.list(page, sl);
	}

	@Override
	public List<StockQuantityVO> quantityInfo(Long stockId) {
		return stockLogMapper.quantityInfo(stockId);
	}

	@Override
	public StockLog build(StockUpdateDTO su) {
		StockLog sl = new StockLog();

		LocalDateTime now = LocalDateTime.now();
		sl.setCreateTime(now);
		sl.setUpdateTime(now);

		String name = SecurityUtils.getUserName();
		sl.setCreateBy(name);
		sl.setUpdateBy(name);

		sl.setOperation(su.getOperation());
		sl.setStatus(su.getStatus());

		Stock stock = su.getStock();
		if (stock != null) {
			sl.setStockId(stock.getId());
			sl.setBeforeQuantity(stock.getQuantity());
		}

		StockDTO dto = su.getStockDTO();
		if (dto == null) {
			return sl;
		}

		sl.setDataKey(dto.getDataKey());
		sl.setQuantity(dto.getQuantity());

		if (dto.getQuantity() > 0) {
			sl.setDirection(StockConstants.Direction.IN);
		} else {
			sl.setDirection(StockConstants.Direction.OUT);
		}

		return sl;
	}

	@Override
	public void asyncLog(StockLog stockLog) {
		try {
			amqpTemplate.convertAndSend(WsmsQueues.STOCK_LOG_CREATE, stockLog);
		} catch (Exception e) {
			log.error("库存日志请求创建失败：{}\n", JSON.toJSONString(stockLog, false), e);
		}
	}

	/**
	 * 监听数据创建队列
	 */
	@RabbitListener(queuesToDeclare = @Queue(WsmsQueues.STOCK_LOG_CREATE))
	void onCreateMessage(StockLog stockLog) {
		try {
			// 禁止重复执行
			if (StrUtil.isNotBlank(stockLog.getDataKey())) {
				LambdaQueryWrapper<StockLog> qw = Wrappers.lambdaQuery();
				qw.eq(StockLog::getStockId, stockLog.getStockId());
				qw.eq(StockLog::getDataKey, stockLog.getDataKey());
				qw.eq(StockLog::getStatus, StockConstants.LogStatus.FINISH);
				if (exists(qw)) {
					return;
				}
			}

			// 创建本次库存日志
			save(stockLog);

			// 同步库存日志流转状态
			if (StrUtil.isBlank(stockLog.getDataKey())) {
				return;
			}

			LambdaUpdateWrapper<StockLog> uw = Wrappers.lambdaUpdate();
			uw.set(StockLog::getStatus, stockLog.getStatus());
			uw.eq(StockLog::getStockId, stockLog.getStockId());
			uw.eq(StockLog::getDataKey, stockLog.getDataKey());
			uw.eq(StockLog::getQuantity, stockLog.getQuantity());
			uw.ne(StockLog::getStatus, stockLog.getStatus());
			update(uw);
		} catch (Exception e) {
			log.error("库存日志创建失败：{}\n", JSON.toJSONString(stockLog, false), e);
		}
	}

}